package com.xiaoyun.alllearning.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.xiaoyun.alllearning.domain.common.PageQuery;
import com.xiaoyun.alllearning.domain.common.PageResult;
import com.xiaoyun.alllearning.domain.dto.UserDTO;
import com.xiaoyun.alllearning.domain.dto.UserExportDTO;
import com.xiaoyun.alllearning.domain.dto.UserQueryDTO;
import com.xiaoyun.alllearning.service.ExcelExportService;
import com.xiaoyun.alllearning.service.FileService;
import com.xiaoyun.alllearning.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class ExcelExportServiceImpl implements ExcelExportService {
    @Resource(name = "localFileServiceImpl")
    private FileService fileService;
    @Autowired
    private UserService userService;

    /**
     * 执行数据库查询和Excel导出，将数据写入到outputStream中
     *
     * @param outputStream
     * @param query
     */
    private void export(OutputStream outputStream, UserQueryDTO query) {
        ExcelWriter excelWriter = EasyExcelFactory.write(outputStream, UserExportDTO.class).build();

        PageQuery<UserQueryDTO> pageQuery = new PageQuery<>();

        pageQuery.setQuery(query);
        pageQuery.setPageSize(2);
        int pageNo = 0;
        PageResult<List<UserDTO>> pageResult;

        do {

            pageQuery.setPageNo(++pageNo);
            log.info("开始导出第{}页数据", pageNo);
            pageResult = userService.query(pageQuery);

            List<UserExportDTO> userExportDTOList = Optional.ofNullable(pageResult.getData())
                    .map(List::stream)
                    .orElseGet(Stream::empty)
                    .map(userDTO -> {
                        UserExportDTO userExportDTO = new UserExportDTO();
                        BeanUtils.copyProperties(userDTO, userExportDTO);
                        return userExportDTO;
                    }).collect(Collectors.toList());
            WriteSheet writeSheet = EasyExcelFactory.writerSheet(pageNo, "第" + pageNo + "页").build();
            excelWriter.write(userExportDTOList, writeSheet);

            log.info("结束导出第{}页数据", pageNo);
        } while (pageResult.getPageNum() > pageNo);

        excelWriter.finish();
        log.info("导出完成");
    }

    @Override
    public void export(UserQueryDTO query, String filename) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        export(outputStream, query);

        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

        fileService.upload(inputStream, filename);

    }

    @Async("exportServiceExecutor")
    @Override
    public void asyncExport(UserQueryDTO query, String filename) {
        log.info("开始异步执行 asyncExport");
        export(query, filename);
    }
}
